package ar.edu.unq.persistencia.gpilla.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import ar.edu.unq.persistencia.gpilla.operaciones.Operacion;

/**
 * TODO: description
 */
public class SessionManager {

    private static SessionManager instancia;

    private static SessionFactory sessionFactory;

    private static ThreadLocal<Session> sessions;

    private SessionManager() {
        super();
        Configuration cfg = new Configuration();
        cfg.configure();
        sessionFactory = cfg.buildSessionFactory();
        sessions = new ThreadLocal<Session>();
    }

    public static SessionManager getInstancia() {
        if (instancia == null) {
            instancia = new SessionManager();
        }
        return instancia;
    }

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public Session getSession() {
        if (sessions.get() == null) {
            sessions.set(sessionFactory.openSession());
        }
        return sessions.get();
    }

    // nullear session cuando termina

    public <T> T ejecutar(final Operacion<T> o) {
        Session session = null;
        // ejecutar recibe una clase (que usa la interfaz operación) y ejecuta el método genérico
        try {
            session = this.getSession();
            session.beginTransaction();
            long startTime = System.currentTimeMillis();
            T retorno = o.ejecutar();
            long endTime = System.currentTimeMillis();
            System.out.println("Tiempo: " + (endTime - startTime));
            session.flush();
            session.getTransaction().commit();
            return retorno;
        } catch (Exception e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            throw new RuntimeException(e);
        } finally {
            if (session != null) {
                session.close();
                sessions.set(null);
            }
        }
    }

    // commit y rollback
}
